package com.lgrglw.search.ke.dao;

import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.queryParser.MultiFieldQueryParser;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.Hits;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.SortField;
import org.apache.lucene.search.highlight.Highlighter;
import org.springframework.beans.factory.annotation.Autowired;
import com.lgrglw.common.page.Page;
import com.lgrglw.common.page.SeachParam;
import com.lgrglw.common.spring.PropertyOper;
import com.lgrglw.search.dao.IndexBaseDao;
import com.lgrglw.search.dao.IndexReaderOper;
import com.lgrglw.search.dao.SearchContants;
import com.lgrglw.search.dao.SearchTools;
import com.lgrglw.search.ke.mapping.ChapterSearchEntity;
import com.lgrglw.search.ke.mapping.DocSearchEntity;
import com.lgrglw.search.ke.mapping.KnowledgeSearchEntity;

/**
 * 知识库文章搜索对象
 * 
 * @author liwei
 * 
 */

public class KnowledgeSearchDao extends
		IndexBaseDao<KnowledgeSearchEntity, String> {

	@Autowired
	private ChapterSearchDao chapterSearchDao;

	/**
	 * 文档搜索
	 * 
	 * @param param
	 *            搜索参数
	 * @return
	 */
	@SuppressWarnings("deprecation")
	public Page<DocSearchEntity> search(SeachParam param) throws Exception {
		IndexReaderOper oper = new IndexReaderOper(PropertyOper.getInstance()
				.getIndexDir()
				+ KnowledgeSearchEntity.alias);
		Analyzer analyzer = new org.wltea.analyzer.lucene.IKAnalyzer();
		BooleanQuery sum = new BooleanQuery();
		QueryParser queryParser = null;
		BooleanQuery highter = new BooleanQuery();// 存放需要高亮显示的属性
		if (param.isAttach()) {// 需要搜索附件
			queryParser = new MultiFieldQueryParser(
					new String[] { "docName", "navigatorPath", "content",
							"menuTitle", "accessoryConent" }, analyzer);
			QueryParser hightParser = new MultiFieldQueryParser(new String[] {
					"docName", "content", "accessoryConent" }, analyzer);
			highter.add(hightParser.parse(param.getKeyWord()),
					BooleanClause.Occur.MUST);
		} else {
			queryParser = new MultiFieldQueryParser(new String[] { "docName",
					"navigatorPath", "content", "menuTitle" }, analyzer);
			QueryParser hightParser = new MultiFieldQueryParser(new String[] {
					"docName", "content", "accessoryConent" }, analyzer);
			highter.add(hightParser.parse(param.getKeyWord()),
					BooleanClause.Occur.MUST);
		}
		Query keyWordQuery = queryParser.parse(param.getKeyWord());
		sum.add(keyWordQuery, BooleanClause.Occur.MUST);
		// 区域
		SearchTools.buildQueryForTerm(sum, "area", param.getArea(),
				SearchContants.MUST);
		// 状态
		SearchTools.buildQueryForTerm(sum, "extStatu", param.getStatus()
				.toString(), SearchContants.MUST);
		// 目录
		SearchTools.buildQueryForWildcard(sum, "docDirectoryIds", param
				.getPath(), SearchContants.MUST);
		Highlighter high = oper.create(highter);// 高亮处理对象
		Sort sort=null;
		//产生排序对象
		if(StringUtils.isNotBlank(param.getFiledName())){
			SortField sf=new SortField(param.getFiledName(),param.getFiledType(),param.isFiledOrder());
			sort=new Sort(sf);
		}
		Hits hit = oper.search(sum, sort);
		// 抽取分页内容
		int startIndex = (param.getPageNo() - 1) * param.getPageSize();// 开始记录
		int endIndex = param.getPageNo() * param.getPageSize();// 结束记录
		int length = hit.length();
		endIndex = Math.min(length, endIndex);// 按照实际记录数取数
		List<String> docId = new LinkedList<String>();
		List<KnowledgeSearchEntity> know = new LinkedList<KnowledgeSearchEntity>();
		for (int i = startIndex; i < endIndex; i++) {
			Document doc = hit.doc(i);
			KnowledgeSearchEntity entity = new KnowledgeSearchEntity();
			entity.setDocId(doc.getField("docId").toString());
			entity.setDocName(doc.getField("docName").toString());
			entity.setDocDirectoryName(doc.getField("docDirectoryName")
					.toString());
			entity.setDocUpdateTime(doc.getField("docUpdateTime").toString());
			entity.setExtStatu(doc.getField("extStatu").toString());
			entity.setOtherStatu(doc.getField("otherStatu").toString());
			entity.setNavigatorPath(doc.getField("navigatorPath").toString());
			entity.setMenuId(doc.getField("menuId").toString());
			entity.setMenuTitle(doc.getField("menuTitle").toString());
			entity.setNavigatorRootId(doc.getField("navigatorRootId")
					.toString());
			// 处理高亮内容
			entity.setContent(oper.getFragment(high, "content", hit.id(i), doc
					.get("content")));
			know.add(entity);
			docId.add(entity.getDocId());
		}
		List<DocSearchEntity> lisp = new LinkedList<DocSearchEntity>();
		if (know.size() > 0) {
			Map<String, List<ChapterSearchEntity>> map = chapterSearchDao
					.search(param.getKeyWord(), param.getArea(), param
							.isAttach(), docId);// 命中的章节对象
			for (int i = 0; i < know.size(); i++) {
				DocSearchEntity docEntity = new DocSearchEntity();
				docEntity.setKnowledgeSearchEntity(know.get(i));
				docEntity.setTargetChapters(map.get(know.get(i).getDocId()));// 命中的章节
				// 处理未命中的章节
				List<ChapterSearchEntity> target = map.get(know.get(i)
						.getDocId());
				String allName[] = know.get(i).getMenuTitle().split(",");// 文档所有的章节名称
				String allId[] = know.get(i).getMenuId().split(",");// 文档所有的章节ID
				List<String> titleNames = Arrays.asList(allName);
				List<String> titleId = Arrays.asList(allId);
				for (ChapterSearchEntity entity : target) {
					titleNames.remove(entity.getMenuTitle());
					titleId.remove(entity.getMenuId());
				}
				List<ChapterSearchEntity> noTarget = new LinkedList<ChapterSearchEntity>();
				for (int x = 0; x < titleNames.size(); x++) {
					ChapterSearchEntity nt = new ChapterSearchEntity();
					nt.setMenuId(titleId.get(x));
					nt.setMenuTitle(titleNames.get(x));
					noTarget.add(nt);
				}
				docEntity.setUnTargetChapters(noTarget);// 未命中的章节
			}
		}
		Page<DocSearchEntity> page = new Page<DocSearchEntity>(lisp, param
				.getPageNo(), length, param.getPageSize());
		return page;
	}

}
